package com.yys.apm.module.report.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yys.apm.module.report.entity.AppData;
import com.yys.apm.module.report.entity.AppDataExt;
import com.yys.apm.module.report.mapper.AppDataExtMapper;
import com.yys.apm.module.report.mapper.AppDataMapper;
import com.yys.apm.module.report.service.IReportService;
import com.yys.apm.module.report.vo.AppDataTreeVO;
import com.yys.apm.module.report.vo.AppDataVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Yingsheng Ye
 * @date 2021-03-11 17:00
 */
@Service
public class ReportServiceImpl implements IReportService {

    @Resource
    private AppDataMapper appDataMapper;

    @Resource
    private AppDataExtMapper appDataExtMapper;

    @Override
    public IPage<AppData> queryAppDataList(AppDataVO appDataVO) {
        IPage<AppData> page = new Page<>(appDataVO.getCurrPage(), appDataVO.getPageSize());
        QueryWrapper<AppData> queryWrapper = new QueryWrapper<>();
        if (!StringUtils.isEmpty(appDataVO.getTraceId())) {
            queryWrapper.eq("trace_id", appDataVO.getTraceId());
        }
        if (!StringUtils.isEmpty(appDataVO.getRequestUrl())) {
            queryWrapper.like("request_url", appDataVO.getRequestUrl());
        }
        if (!StringUtils.isEmpty(appDataVO.getStartTime()) && !StringUtils.isEmpty(appDataVO.getEndTime())) {
            queryWrapper.between("create_time", appDataVO.getStartTime(), appDataVO.getEndTime());
        }
        queryWrapper.eq("type", "ControllerCollect");
        if (!StringUtils.isEmpty(appDataVO.getSortField())) {
            queryWrapper.orderBy(true, appDataVO.isSortAsc(),
                    appDataVO.getSortField());
        }
        return appDataMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<AppDataTreeVO> queryAppDataByTraceId(String traceId) {
        QueryWrapper<AppData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trace_id", traceId);
        queryWrapper.orderBy(true, true, "start_time");
        List<AppData> treeList = appDataMapper.selectList(queryWrapper);
        List<AppDataTreeVO> rootList = new ArrayList<>();
        List<AppDataTreeVO> allList = new ArrayList<>();
        for (AppData appData : treeList) {
            AppDataTreeVO appDataTreeVO = new AppDataTreeVO();
            BeanUtils.copyProperties(appData, appDataTreeVO);
            appDataTreeVO.setLabel(appData.getClassName() + "#" + appData.getMethodName());
            if (StringUtils.isEmpty(appData.getParentId())) {
                rootList.add(appDataTreeVO);
            }
            allList.add(appDataTreeVO);
        }
        for (AppDataTreeVO tree : rootList) {
            recursionFn(allList, tree);
        }
        return rootList;
    }

    @Override
    public Map<String, Object> queryAppDataDetails(Integer dataId) {
        Map<String, Object> returnMap = new HashMap<>();
        AppData appData = appDataMapper.selectById(dataId);
        returnMap.put("appInfo", appData);
        QueryWrapper<AppData> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("trace_id", appData.getTraceId());
        queryWrapper.orderBy(true, true, "start_time");
        List<AppData> dataList = appDataMapper.selectList(queryWrapper);
        returnMap.put("relList", dataList);//关联数据
        QueryWrapper<AppDataExt> dataExtQueryWrapper = new QueryWrapper<>();
        dataExtQueryWrapper.eq("data_id", dataId);
        List<AppDataExt> appDataExtList = appDataExtMapper.selectList(dataExtQueryWrapper);
        Map<String, Object> details = new HashMap<>();
        appDataExtList.forEach(item -> {
            details.put(item.getExtLabel(), item.getExtValue());
        });
        if (!StringUtils.isEmpty(appData.getVisitUserId())) {
            details.put("visitUserId", appData.getVisitUserId());
        }
        if (!StringUtils.isEmpty(appData.getHostIp())) {
            details.put("hostIp", appData.getHostIp());
        }
        if (!StringUtils.isEmpty(appData.getHostName())) {
            details.put("hostName", appData.getHostName());
        }
        if (!StringUtils.isEmpty(appData.getRequestUrl())) {
            details.put("requestUrl", appData.getRequestUrl());
        }
        returnMap.put("details", details); //获取扩展信息
        return returnMap;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<AppDataTreeVO> list, AppDataTreeVO tree) {
        List<AppDataTreeVO> childrenList = getChildrenList(list, tree);
        tree.setChildren(childrenList);
        for (AppDataTreeVO next : childrenList) {
            if (hasChildren(list, next)) {
                recursionFn(list, next);
            }
        }
    }

    /**
     * 得到子节点列表
     */
    private List<AppDataTreeVO> getChildrenList(List<AppDataTreeVO> list, AppDataTreeVO tree) {
        List<AppDataTreeVO> childrenList = new ArrayList<>();
        for (AppDataTreeVO next : list) {
            if (!StringUtils.isEmpty(next.getParentId()) && next.getParentId().equals(tree.getSpanId())) {
                childrenList.add(next);
            }
        }
        return childrenList;
    }

    /**
     * 判断是否有子节点
     */
    private boolean hasChildren(List<AppDataTreeVO> list, AppDataTreeVO tree) {
        return getChildrenList(list, tree).size() > 0;
    }
}
